import { ref, computed } from 'vue'
import { defineStore } from 'pinia'

/**
 *  总结：
 *  外部组件使用：const store = useCounterStore()
 *  1. 这里的数据，也就是store数据是经过reactive处理的，所以即使内部我们使用ref定义了变量，但是外部使用的时候也不需要在使用.value来读取数据
 *  例如：外部使用：store.count即可， 而不是store.count.value
 *  
 * 2. 可以给store进行解构赋值，但是解构赋值后的count就会丢失响应式（解构赋值相当于重新创建了一个对象来接收了store中对应的变量），例如：
 *  const { count } = useCounterStore() 在修改count时，虽然count的值实际上已经改变了，但是页面不会跟着改变，也就是不会同步
 * 
 * 3. 如何解决2中解构赋值响应式丢失的问题？
 *  import { storeToRefs } from 'pinia'
 *  使用storeToRefs()方法， 保证解构出来的数据都是一个响应式的ref数据：
 *  例如： const store = useCounterStore()
 *        const { count } = storeToRefs(store)
 *  这样就可保持响应式，但是要注意：此时的store中的响应式对象都被修改为ref类型的，所以在使用时必须加上.value，例如: num.value = 2
 * 
 *  4. pinia中修改数据：
 * 
 *  第一种方法：(不解构)直接赋值   例如：const store = useCounterStore() 修改：store.num = 2
 *  第一种方法：使用storeToRefs解构后赋值  例如：const store = useCounterStore() const { count } = storeToRefs(store) 修改：num.value = 2
 *  第三种方法(不推荐)：const store = useCounterStore()  store.$patch({num: 200}) ，因为$patch()中的{}对象需要整体替换
 *  第4种方法(推荐)：const store = useCounterStore()  store.$patch((state)=>{state.num = 200}) ，$patch()接收一个方法，可以单独处理每一个对象
 * 
 *  第五种方法（最推荐的）： 内部的变量需要在内部定义对应的方法来修改内部的变量，尽量不要在外部组件中修改pinia内部的变量
 * 
 * 内部的变量和方法需要分开解构
 * 内部变量的解构需要响应式，所以需要使用storeToRefs解构
 * 内部方法不需要响应式，就不用使用storeToRefs解构了
 * 例如：
 * const store = useCounterStore() 
 * 变量解构（需要响应式）
 * const { count } = storeToRefs(store)
 * 方法解构（不需要响应式）
 * const { increment } = store
 * 
 * 
 * reactive定义的对象整体重新赋值后丢失响应式，但是ref变量通过.value方法赋值后不会丢失响应式
 * reactive定义的对象整体重新赋值后又不想丢失响应式，可以将其修改为ref，或者重新赋值一个reactive()包裹的变量
 * 
 * 一键重置：
 * 恢复内部变量的初始值，仅适用于选项式api
 * 选项式：store.$reset() 
 * 
 * 组合式需要自己定义一个重置方法来将内部变量重新设置为初始值并return出去
 * 
 * 
 */


// 组合式写法
export const useCounterStore = defineStore('counter', () => {
  const count = ref(0)
  const doubleCount = computed(() => count.value * 2)
  function increment() {
    count.value++
  }

  return { count, doubleCount, increment }
})
